The majority of Windows applications include one or more toolbars, which offer the end user the convenience of executing the most common commands with a click of the mouse. Toolbars should never replace menus—and for good reason: menus can be operated with the keyboard; toolbars can't—but they surely make a program more usable and give it a modern look and feel.
Visual Basic comes with a Toolbar control that can contain buttons and other controls and that can be interactively customized by the end user. The Visual Basic 6 version adds the flat style made popular by Microsoft Internet Explorer and the support for building drop-down menus.
The Toolbar control exposes the Buttons collection, which in turn contains Button objects. Each Button object can be an actual push button, a separator, or a placeholder for another control placed on the toolbar (typically a TextBox control or a ComboBox control). In addition, a Button object exposes the ButtonsMenus collection, where each ButtonMenu object is an item of a drop-down menu. (If the Button object isn't a drop-down menu, this collection is empty.)
In most cases, you define the appearance of a Toolbar at design time and then simply react to user's clicks on its buttons. You have two ways to work with a Toolbar at design time: by using the Toolbar Wizard or by manually setting properties. The two methods aren't mutually exclusive: In most cases, in fact, you might find it convenient to create a first version of a Toolbar control using the wizard and then refine it in its Properties dialog box.
The Toolbar Wizard is a new add-in provided with Visual Basic 6. But you won't find this wizard in the list of installable add-ins in the Add-In Manager dialog box. Instead, you have to install the Application Wizard add-in: After you do this, you'll find the Toolbar Wizard command in the Add-In menu. If you select this command, the wizard adds a new Toolbar control to the current form and lets you customize it. Or you can place a Toolbar control on the form yourself, and the wizard will be automatically activated.
Using the Toolbar Wizard is simple. You have a list of buttons in the leftmost list box (see Figure 10-14) from which you select the buttons you want to add to the Toolbar control. You can move items between the two list boxes and change their order in the toolbar by using the provided push buttons, or you can use drag-and-drop. The wizard also creates the companion ImageList control on the form. When you complete a toolbar, you'll be asked whether you want to save it in an .rwp profile file, which lets you speed up the creation of similar toolbars in future applications.
Figure 10-14. Creating a toolbar using the Toolbar Wizard.
After you create a toolbar, you can access its Property Pages by right-clicking on it and choosing Properties. The General tab of the Property Pages dialog box includes most of the design-time properties that let you control the fine points of the appearance and behavior of a Toolbar control, as shown in Figures 10-15 and 10-16. For example, you make the following decisions: Whether the end user can customize the toolbar at run time (AllowCustomize property), whether the toolbar will wrap on multiple lines when the form is resized (Wrappable property), whether ToolTips are visible (ShowTips property), and what the default size of buttons (ButtonWidth and ButtonHeight properties) is. If necessary, buttons are automatically enlarged to account for their caption or image, so in most cases you don't need to edit the default values of the latter two properties.
A few new properties let you access the most interesting features introduced in Visual Basic 6. You can create flat toolbars by setting the Style property to the value 1-tbrFlat, and you can use the TextAlignment property to modify the alignment of a button's caption with respect to the button's image (0-tbrTextAlignBottom or 1-tbrTextAlignRight).
A toolbar's button can be in three possible states: normal, disabled, or selected. (The selected state occurs when the mouse passes over the button if Style is 1-tbrFlat.) Instead of having three properties to point to different images of the same ImageList control, the Toolbar control uses a different approach: Each Button object exposes only one Image property—an index or a string key—and the state of the button implicitly affects which ImageList control will be used. You assign these three ImageList controls to the ImageList, DisabledImageList, and HotImageList properties either at design time or at run time. For example, you can mimic the behavior of Internet Explorer 4 by using a set of black-and-white icons for the normal state and a set of colorful icons for the selected state. If you don't assign the latter two properties, the Toolbar automatically creates a suitable image for the disabled or selected state.
Figure 10-15. The General tab of the Property Pages dialog box of a Toolbar control.
Figure 10-16. The Buttons tab of the Property Pages dialog box of a Toolbar control.
A Toolbar control without any Button objects is useless. You can add Button objects using the Toolbar Wizard, as I explained previously, or you can do it in the Buttons tab of the Property Pages dialog box, as you can see in Figure 10-16. Each Button has a Caption property (use an empty string if you want to display only the icon), an optional Description that appears during a customization operation, a Tag property, a Key in the Buttons collection (optional, but use it to improve the readability of your code), a ToolTipText that appears if the Toolbar's ShowTips property is True, and an Image index or key to the associated ImageList controls.
Style is the most interesting property of a Button object. This property affects the appearance and behavior of the button and can be assigned one of the following values: 0-tbrDefault (a normal button, which behaves like a push button), 1-tbrCheck (a button that stays down when pressed, much like a CheckBox control), 2-tbrButtonGroup (a button that belongs to a group in which only one item can be in the selected state, similar to an OptionButton control), 3-tbrSeparator (a separator of fixed width), 4-tbrPlaceholder (a separator whose size depends on the Width property; this style is used to make room for another control placed on the toolbar), or 5-tbrDropDown (a button with a down arrow beside it, which displays a drop-down menu when clicked).
When the Style property is set to the value 5-tbrDropDown, you can add one or more ButtonMenu objects to the current Button. (You can create ButtonMenu items regardless of the button's style, but they're visible only when the style is tbrDropDown.) Each ButtonMenu object has a Text property (the caption of the menu line), an optional Key in the ButtonMenus collection, and a Tag property. Unfortunately, you can't associate an image with a ButtonMenu object: Drop-down menus are inherently text-only, which definitely contrasts with the graphical nature of the Toolbar control. See Figure 10-17 for an example of a Toolbar control whose first button has an associated drop-down menu.
Figure 10-17. A toolbar with a drop-down menu.
Once you have added a Toolbar control to a form, you have to trap the user's actions on it. You might also need to programmatically build the control at run time or let the user customize it and save the new layout for subsequent sessions.
You can create new Button objects at run time using the Add method of the Buttons collection, which has the following syntax:
Add([Index], [Key], [Caption], [Style], [Image]) As Button |
Index is the position at which the Button object will be inserted in the collection, Key is its optional string key, Caption is the text visible on the toolbar, Style determines the type of the button being added (0-tbrNormal, 1-tbrCheck, 2tbrButtonGroup, 3-tbrSeparator, 4-tbrPlaceholder, or 5-tbrDropDown), and Image is the index or the key of an image in the three companion ImageList controls.
You might want to set a few additional properties when you're creating a Button object, such as Width (for placeholder buttons) and ToolTipText. Buttons whose style is tbrCheck or tbrButtonGroup can be created in a pressed state by assigning 1-tbrPressed to the Value property. Here's an example of code that adds a few buttons:
' A button that can be in an on or off state Dim btn As Button Set btn = Toolbar1.Buttons.Add(, , , tbrCheck, "Lock") btn.Value = tbrPressed ' A separator Toolbar1.Buttons.Add, , , tbrSeparator ' Two buttons that are mutually exclusive Set btn = Toolbar1.Buttons.Add(, , , tbrButtonGroup, "Green") Set btn = Toolbar1.Buttons.Add(, , , tbrButtonGroup, "Red") btn.Value = tbrPressed |
You can place any control in the toolbar by creating a Button object with the Style property set to tbrPlaceholder and then moving the control to the correct position. For example, let's say that you want to place the cboFontSizes control in the toolbar:
' Create a placeholder of proper width. Dim btn As Button Set btn = Toolbar1.Buttons.Add(, , , tbrPlaceholder) btn.Width = cboFontSizes.Width ' Move the ComboBox control over the placeholder button. Set cboFontSizes.Container = Toolbar1 cboFontSizes.Move btn.Left, btn.Top |
If you create a Button object whose Style property is tbrDropDown, you can add one or more items to its ButtonMenus collection by using the collection's Add method:
Add ([Index], [Key], [Text]) As ButtonMenu |
Index is the position in the collection, Key is an optional key, and Text is the caption of the menu item. The piece of code below adds one drop-down Button object with a menu of three items.
Dim btn As Button Set btn = Toolbar1.Buttons.Add(, , , tbrDropDown, "New") With btn.ButtonMenus .Add , , "File" .Add , , "Document" .Add , , "Image" End With |
When the user clicks on a button, the Toolbar control fires a ButtonClick event, so it's easy to execute a piece of code when this happens:
Private Sub Toolbar1_ButtonClick(ByVal Button As MSComCtlLib.Button) Select Case Button.Key Case "New" Call mnuFileNew_Click Case "Save" Call mnuFileSave_Click ' And so on. End Select End Sub |
Visual Basic 6 introduces two new events, both of which are related to drop-down menus. The ButtonDropDown event fires when the user opens a drop-down menu. You can use this event to create or modify the menu on the fly—for example, by setting the Visible or Enabled property of its individual ButtonMenu items or by adding new menu lines:
Private Sub Toolbar1_ButtonDropDown(ByVal Button As MSComctlLib.Button) ' Make the "Open | Image" command unavailable if necessary. If Button.Caption = "Open" Then Button.ButtonMenus("Image").Enabled = ImagesAreEnabled End If End Sub |
The ButtonMenuClick event fires when the end user actually selects a command in a drop-down menu:
Private Sub Toolbar1_ButtonMenuClick(ByVal ButtonMenu As MSComctlLib.ButtonMenu) Select Case ButtonMenu.Key Case "Document" Call mnuFileNewDocument Case "Image" Call mnuFileNewImage End Select End Sub |
You can allow for users to customize the Toolbar control if you want. You can choose from two ways to achieve this: You set the AllowCustomization property to True to let users enter customization mode by double-clicking on the toolbar, or you programmatically enter customization mode by executing the Toolbar's Customize method. The latter approach is necessary if you want to provide this capability only to a restricted group of users:
Private Sub Toolbar1_DblClick() If UserIsAdministrator Then Toolbar1.Customize End Sub |
Whatever method you choose, you end up displaying the Customize Toolbar dialog box, shown in Figure 10-18.
Figure 10-18. The Customize Toolbar dialog box.
When the user closes this dialog box, the Toolbar control raises a Change event. (Beware: This event occurs even if the user made no changes to the toolbar's layout.) Within this event procedure, you should execute a SaveToolbar method, which has the following syntax:
SaveToolbar Key, Subkey, Value |
Key is the name of a Registry key, SubKey is the name of a Registry subkey, and Value is the name of a Registry value; together, these arguments define a location in the system Registry where the layout of the toolbar is stored. For example, you can use them to save different layouts depending on the application's name, the user currently logged in, and the particular toolbar:
Private Sub Toolbar1_Change() Toolbar1.SaveToolbar "MyApplication", UserName, "MainFormToolbar" End Sub |
You restore these settings using the RestoreToolbar method, typically in the Form_Load event procedure:
Private Sub Form_Load() Toolbar1.RestoreToolbar "MyApplication", UserName, "MainFormToolbar" End Sub |
NOTE
Oddly, the RestoreToolbar method raises a Change event. This behavior is usually harmless because the code in this event procedure proceeds to save the toolbar again in the Registry (adding just a little overhead to the form-loading process). However, if the Toolbar object's Change event procedure contains other, time-consuming statements, they might slow down your code and even cause an unexpected error.
When the Customize Toolbar dialog box is active, users can delete existing buttons, restore buttons that had been previously deleted, or change the order of buttons in the toolbar. If you want to let users add buttons, you must create such buttons at design time, run the application, invoke the Customize Toolbar, and delete these extra buttons. The deleted buttons will be available in the leftmost list box in the Customize Toolbar dialog box in case a user wants to restore them.